package com.yuju.controller.wxPay;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.xml.sax.InputSource;

import com.alibaba.fastjson.JSONObject;
import com.wxpay.demo.WxPayResult;
import com.yuju.common.Result;
import com.yuju.enums.ReturnStatusEnum;
import com.yuju.enums.WxPayForScanReturnCodeEnum;
import com.yuju.guest.service.WxPayService;
import com.yuju.order.service.IReserverService;
import com.yuju.util.IpUtil;
import com.yuju.util.MathUtil;

/**
 * 类名：WxPayController  <br />
 *
 * 功能：微信支付接口
 *
 * @author : xuehj <br />
 * @Date : 2017年9月22日 下午5:07:29  <br />
 * @version : 1.1 <br />
 */
@Controller
@RequestMapping("wxPay")
public class WxPayController extends com.yuju.controller.base.BaseController {
	
	@Autowired
	private WxPayService wxPayService;
	@Autowired
	private IReserverService reserveService;
	
	/**
	 * 功能：获取微信预支付package<br/>
	 * 统一下单
	 *@param orderNo 订单号
	 *@param openId 用户标识
	 * @author xuehj
	 * @Date 2017年9月27日 上午10:01:44 <br/>
	 */
	@RequestMapping("getPayPackage")
	@ResponseBody
	public Result getPayPackage(@RequestBody JSONObject jsonObject) {
		Result result = new Result();
		String orderNo = jsonObject.getString("orderNo");
		String openId = jsonObject.getString("openId");
		/*校验*/
	/*	Map<String, String> fail = new HashMap<>();
		if(orderNo == null || openId == null ){
			fail.put("orderNo  openId ", "都不能为空");
			return validateError(fail);
		}*/
			//String openId = "o3jyiw_uwTYpmSvWGShyIge1KrM4";
			//openId = getUser().getOpenId();
			String payPackage = wxPayService.getPayPackage(orderNo, openId, IpUtil.getIpAddr(getRequest()));
			if (null != payPackage) {
				result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
				result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getDesc());
				result.setData(payPackage);
			} else {
				result.setStatus(ReturnStatusEnum.FAILURE.getCode());
				result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_FAILURE.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_FAILURE.getDesc());
			}
		return result;
	}
	
	/**
	 * 微信支付完成后的回调函数
	 * @author xuehj
	 * @date 2017-09-22
	 * 
	 * @throws IOException
	 * @throws JDOMException 
	 */
	@RequestMapping(value = "/callback")
	public void wxPayCallback() throws IOException, JDOMException {
		System.out.print("***微信支付回调数据开始");
		String inputLine;
		String notityXml = "";

			while ((inputLine = getRequest().getReader().readLine()) != null) {
				notityXml += inputLine;
			}
			getRequest().getReader().close();
		System.out.println("接收到的报文：" + notityXml);

		@SuppressWarnings("rawtypes")
		Map m = parseXmlToList2(notityXml);
		WxPayResult wpr = new WxPayResult();
		wpr.setAppid(m.get("appid").toString());
		wpr.setBankType(m.get("bank_type").toString());
		wpr.setCashFee(m.get("cash_fee").toString());
		wpr.setFeeType(m.get("fee_type").toString());
		wpr.setIsSubscribe(m.get("is_subscribe").toString());
		wpr.setMchId(m.get("mch_id").toString());
		wpr.setNonceStr(m.get("nonce_str").toString());
		wpr.setOpenid(m.get("openid").toString());
		wpr.setOutTradeNo(m.get("out_trade_no").toString());
		wpr.setResultCode(m.get("result_code").toString());
		wpr.setReturnCode(m.get("return_code").toString());
		wpr.setSign(m.get("sign").toString());
		wpr.setTimeEnd(m.get("time_end").toString());
		wpr.setTotalFee(m.get("total_fee").toString());
		wpr.setTradeType(m.get("trade_type").toString());
		wpr.setTransactionId(m.get("transaction_id").toString());
		/*wpr.setAttach(m.get("attach").toString());
		if (Utils.isNotNull(m.get("store_id")))
			wpr.setStoreid(m.get("store_id").toString());*/
		
		//分转换成元
		String _amt = wpr.getTotalFee();
		String amt = MathUtil.div(_amt, "100",2);

		String resXml;
		if ("SUCCESS".equals(wpr.getResultCode())) {
			// 支付成功
			// resXml =
			// "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
			resXml = "SUCCESS";

			String _billno = wpr.getOutTradeNo();

			System.out.println("======================================>" + _billno);
			
			// 更新预定单状态
			reserveService.wxPayFinished(_billno);
		} else {
			resXml = "FAIL";
		}
		System.out.println("***微信支付回调数据结束");
		BufferedOutputStream out = new BufferedOutputStream(this.getResponse().getOutputStream());
		out.write(resXml.getBytes());
		out.flush();
		out.close();
	}
	
	/**
	 * 解析微信通知xml
	 * 
	 * @param xml
	 * @author xuehj
	 * @return
	 * @throws IOException 
	 * @throws JDOMException 
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private Map parseXmlToList2(String xml) throws JDOMException, IOException {
		Map retMap = new HashMap();
			StringReader read = new StringReader(xml);
			// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
			InputSource source = new InputSource(read);
			// 创建一个新的SAXBuilder
			SAXBuilder sb = new SAXBuilder();
			// 通过输入源构造一个Document
			Document doc = (Document) sb.build(source);
			Element root = doc.getRootElement();// 指向根节点
			List<Element> es = root.getChildren();
			if (es != null && es.size() != 0) {
				for (Element element : es) {
					retMap.put(element.getName(), element.getValue());
				}
			}
		return retMap;
	}
	/**
	 * 普通商户微信刷卡扫码支付
	 * 功能：<br/>
	 *@param  orderNo 订单号
	 *@param authCode 授权码
	 *@param totalMoney  金额
	 * @author sunyl
	 * @throws Exception 
	 * @Date 2018年1月17日 下午4:55:00 <br/>
	 */
	@RequestMapping("microPay")
	@ResponseBody
	public Result microPay(@RequestBody JSONObject jsonObject) throws Exception {
			String orderNo = jsonObject.getString("orderNo");
			String authCode = jsonObject.getString("authCode");
			String flag = jsonObject.getString("flag");
			BigDecimal totalMoney = jsonObject.getBigDecimal("totalMoney");
			/*校验*/
			Map<String, String> fail = new HashMap<>();
			if(orderNo == null || authCode == null ||totalMoney == null){
				fail.put("orderNo  authCode totalMoney", "都不能为空");
				return validateError(fail);
			}
		return  wxPayService.microPay(totalMoney, orderNo, authCode, "8.8.8.8",flag);
	}
	/**
	 * 服务商模式得刷卡支付
	 * 功能：<br/>
	 *@param  orderNo 订单号
	 *@param authCode 授权码
	 *@param totalMoney  金额
	 * @author sunyl
	 * @Date 2018年2月6日 上午9:55:45 <br/>
	 *//*
	@RequestMapping("microPayForService")
	@ResponseBody
	public Result microPayForService(@RequestBody JSONObject jsonObject) throws Exception {
		String orderNo = jsonObject.getString("orderNo");
		String authCode = jsonObject.getString("authCode");
		String flag = jsonObject.getString("flag");
		BigDecimal totalMoney = jsonObject.getBigDecimal("totalMoney");
		校验
		Map<String, String> fail = new HashMap<>();
		if(orderNo == null || authCode == null ||totalMoney == null){
			fail.put("orderNo  authCode totalMoney", "都不能为空");
			return validateError(fail);
		}
		return  wxPayService.microPayForService(totalMoney, orderNo, authCode, "8.8.8.8",flag);
	}*/
	/**
	 * 微信插銷訂單
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @throws Exception 
	 * @Date 2018年1月17日 下午4:55:00 <br/>
	 */
	@RequestMapping("reverse")
	@ResponseBody
	public Result reverse(@RequestBody JSONObject jsonObject) throws Exception {
		String orderNo = jsonObject.getString("orderNo");
		String authCode = jsonObject.getString("authCode");
		String flag = jsonObject.getString("flag");
		BigDecimal totalMoney = jsonObject.getBigDecimal("totalMoney");
		/*校验*/
		Map<String, String> fail = new HashMap<>();
		if(orderNo == null || authCode == null ||totalMoney == null){
			fail.put("orderNo  authCode totalMoney", "都不能为空");
			return validateError(fail);
		}
		return  wxPayService.reverse(totalMoney, orderNo, authCode, "8.8.8.8",flag);
	}
	/**
	 * 退款
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @Date 2018年2月6日 下午5:51:11 <br/>
	 */
	/*@RequestMapping("refundForService")
	@ResponseBody
	public Result refundForService(@RequestBody JSONObject jsonObject) throws Exception {
		String orderNo = jsonObject.getString("orderNo");
		String transactionId = jsonObject.getString("transactionId");
		String flag = jsonObject.getString("flag");
		BigDecimal totalFee = jsonObject.getBigDecimal("totalFee");
		BigDecimal refundFee = jsonObject.getBigDecimal("refundFee");
		校验
		Map<String, String> fail = new HashMap<>();
		if(orderNo==null || transactionId==null||totalFee==null ||refundFee==null){
			fail.put("orderNo transactionId totalFee refundFee", "都不能为空");
			return validateError(fail);
		}
		return  wxPayService.refundForService(refundFee, totalFee,orderNo, transactionId, flag);
	}*/
	/**
	 * 退款
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @Date 2018年2月6日 下午5:51:11 <br/>
	 */
	@RequestMapping("refund")
	@ResponseBody
	public Result refund(@RequestBody JSONObject jsonObject) throws Exception {
		String orderNo = jsonObject.getString("orderNo");
		String transactionId = jsonObject.getString("transactionId");
		String flag = jsonObject.getString("flag");
		BigDecimal totalFee = jsonObject.getBigDecimal("totalFee");
		BigDecimal refundFee = jsonObject.getBigDecimal("refundFee");
		/*校验*/
		Map<String, String> fail = new HashMap<>();
		if(orderNo==null || transactionId==null||totalFee==null ||refundFee==null){
			fail.put("orderNo transactionId totalFee refundFee", "都不能为空");
			return validateError(fail);
		}
		return  wxPayService.refund(refundFee, totalFee,orderNo, transactionId, flag);
	}
	/**
	 * 微信刷卡扫码支付查询
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @throws Exception 
	 * @Date 2018年1月18日 上午10:46:00 <br/>
	 */
	@RequestMapping("orderQuery")
	@ResponseBody
	public Result orderQuery(@RequestBody JSONObject jsonObject) throws Exception {
		Result result = new Result();
		String orderNo = jsonObject.getString("orderNo");
		Map<String, String> fail = new HashMap<>();
		if(orderNo==null ){
			fail.put("orderNo ", "不能为空");
			return validateError(fail);
		}
		Map resultMap = wxPayService.orderQuery(orderNo);
		String retrun_code = resultMap.get("return_code").toString();
		String result_code = resultMap.get("result_code").toString();
		Object err_code_des = resultMap.get("err_code_des");
		if(retrun_code.equals("SUCCESS")){
			if(result_code.equals("SUCCESS")){
				String trade_state = resultMap.get("trade_state").toString();
				Object trade_state_desc = resultMap.get("trade_state_desc");
				if(trade_state.toString().equals("SUCCESS")){
					result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
					result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getDesc());
				}else if(trade_state.equals("USERPAYING")){
					result.setStatus(ReturnStatusEnum.FAILURE.getCode());
					result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.USERPAYING.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.USERPAYING.getDesc());
				}else{
					result.setStatus(ReturnStatusEnum.FAILURE.getCode());
					result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_FAILURE.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_FAILURE.getDesc());
					result.setData(trade_state_desc);
				}
			}else{
				result.setStatus(ReturnStatusEnum.FAILURE.getCode());
				result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getDesc());
				result.setData(err_code_des);
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_FAILURE.getDesc());
			result.setData(err_code_des);
			}
		return result;
	}
	
	/**
	 * 服务商微信刷卡扫码支付查询
	 * 功能：<br/>
	 *
	 * @author sunyl
	 * @throws Exception 
	 * @Date 2018年1月18日 上午10:46:00 <br/>
	 */
	@RequestMapping("orderQueryForService")
	@ResponseBody
	public Result orderQueryForService(@RequestBody JSONObject jsonObject) throws Exception {
		Result result = new Result();
		String orderNo = jsonObject.getString("orderNo");
		Map<String, String> fail = new HashMap<>();
		if(orderNo==null ){
			fail.put("orderNo ", "不能为空");
			return validateError(fail);
		}
		Map resultMap = wxPayService.orderQueryForService(orderNo);
		String retrun_code = resultMap.get("return_code").toString();
		String result_code = resultMap.get("result_code").toString();
		Object err_code_des = resultMap.get("err_code_des");
		if(retrun_code.equals("SUCCESS")){
			if(result_code.equals("SUCCESS")){
				String trade_state = resultMap.get("trade_state").toString();
				Object trade_state_desc = resultMap.get("trade_state_desc");
				if(trade_state.toString().equals("SUCCESS")){
					result.setStatus(ReturnStatusEnum.SUCCESS.getCode());
					result.setMsg(ReturnStatusEnum.SUCCESS.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_SUCCESS.getDesc());
				}else if(trade_state.equals("USERPAYING")){
					result.setStatus(ReturnStatusEnum.FAILURE.getCode());
					result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.USERPAYING.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.USERPAYING.getDesc());
				}else{
					result.setStatus(ReturnStatusEnum.FAILURE.getCode());
					result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
					result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_FAILURE.getCode());
					result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_FAILURE.getDesc());
					result.setData(trade_state_desc);
				}
			}else{
				result.setStatus(ReturnStatusEnum.FAILURE.getCode());
				result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
				result.setReturnCode(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getCode());
				result.setReturnMsg(WxPayForScanReturnCodeEnum.QUERY_FAILURE.getDesc());
				result.setData(err_code_des);
			}
		}else{
			result.setStatus(ReturnStatusEnum.FAILURE.getCode());
			result.setMsg(ReturnStatusEnum.FAILURE.getDesc());
			result.setReturnCode(WxPayForScanReturnCodeEnum.PAY_FAILURE.getCode());
			result.setReturnMsg(WxPayForScanReturnCodeEnum.PAY_FAILURE.getDesc());
			result.setData(err_code_des);
		}
		return result;
	}
	
	
}
